#pragma once

#include "Type.h"
#include "Common.h"
#include <string>

///
/// @brief 指针/数组统一类型（取代 PointerType 与 ArrayType）
///
class PointerType : public Type {
public:
    /// @brief 构造函数（arraySize = 0 表示普通指针；>0 表示数组）
    explicit PointerType(const Type* pointeeType, bool isArray = false, int arraySize = 0)
        : Type(PointerTyID), pointeeType(pointeeType), isArrayFlag(isArray), arraySize(arraySize)
    {
        if (!pointeeType || pointeeType->getSize() <= 0) {
            minic_log(LOG_WARNING, "PointerType element type has invalid size");
            totalSize = 0;
        } else {
            totalSize = isArray ? arraySize * pointeeType->getSize() : sizeof(void*);
        }

        if (pointeeType->isPointerType()) {
            Instanceof(pType, const PointerType*, pointeeType);
            rootType = pType->getRootType();
            depth = pType->getDepth() + 1;
        } else {
            rootType = pointeeType;
            depth = 1;
        }
    }

    /// @brief 指针或数组统一获取接口（不缓存）
    static PointerType* get(const Type* pointee, bool isArray = false, int arraySize = 0) {
        return new PointerType(pointee, isArray, arraySize);
    }

    // ---------- 原 PointerType 功能保留 ----------
    const Type* getRootType() const { return rootType; }
    const Type* getPointeeType() const { return pointeeType; }
    int32_t getDepth() const { return depth; }

    // ---------- 原 ArrayType 功能整合 ----------
    bool isArrayType() const override { return isArrayFlag; }
    int getLength() const { return isArrayFlag ? arraySize : 0; }

    const Type* getElementType() const {
        return isArrayFlag ? pointeeType : nullptr;
    }

    int getSize() const override { return totalSize; }

    /// 若元素类型还是数组，返回下一层，否则 nullptr
    PointerType* getNextArrayType() const {
        if (isArrayFlag && pointeeType->isArrayType()) {
            return const_cast<PointerType*>(static_cast<const PointerType*>(pointeeType));
        }
        return nullptr;
    }

    std::string toString() const override {
        if (!pointeeType) return "[invalid]";
        if (isArrayFlag) {
            return "[" + std::to_string(arraySize) + " x " + pointeeType->toString() + "]";
        } else {
            return pointeeType->toString() + "*";
        }
    }

    bool equals(const Type* other) const override {
        if (this == other) return true;
        auto* otherPtr = dynamic_cast<const PointerType*>(other);
        if (!otherPtr) return false;

        return pointeeType->equals(otherPtr->pointeeType) &&
               isArrayFlag == otherPtr->isArrayFlag &&
               arraySize == otherPtr->arraySize;
    }

    bool isArray() const {
        return this->isArrayFlag;
    }

private:
    const Type* pointeeType = nullptr;
    const Type* rootType = nullptr;
    int32_t depth = 1;

    // 数组特性字段
    bool isArrayFlag = false;
    int arraySize = 0;
    int totalSize = 0;
};
